<?php 
/**
 * Pagelist
 * 
 * 单例模式
 * 分页计算类
 *
 * @author   songhuan <iphper@yeah.net>
 * @version   $Id: Pagelist.php 1 2010-08-10 14:40:00Z $
 */
class Pagelist
{
	/**
	 * @var int 每页显示的记录数
	 */
	private $_perPageResults = 0;
	
	/**
	 * @var int 当前的页
	 */
	private $_currentPage = 1;
	
	/**
	 * @var int 总的记录条数
	 */
	private $_totalResults = 0;
	
	/**
	 * @var int 当前页的开始的记录位置(LIMIT $_startResult, $_perPageResults)
	 */
	private $_startResult = 0;
	
	/**
	 * @var int 总页数
	 */
	private $_totalPages = 0;
	
	/**
	 * @var int 每页显示页码数
	 */
	private $_perPagePages = 0;
	
	/**
	 * @var int 每个页面显示$_perPagePages个页码，一共分多少个页码显示
	 */
	private $_P_totalPages = 0;
	
	/**
	 * @var int 每个页面显示$_perPagePages个页码，当前是第多少个页码
	 */
	private $_P_currentPage = 0;
	
	/**
	 * @var int 当前页的开始页码
	 */
	private $_startPage = 0;
	
	/**
	 * @var int 当前页的结束页码
	 */
	private $_endPage = 0;
	
	/**
	 * @var int 当前页的开始页的上一页
	 */
	private $_prePage = 0;
	
	/**
	 * @var int 当前页的结束页的下一页
	 */
	private $_nextPage = 0;
	
	/**
	 * @var 页码链接方式::a标签的方式
	 */
	const URL_A  = 1;
	
	/**
	 * @var 页码链接方式::js的方式
	 */
	const URL_JS = 2;
	
	private static $_instance = null;
	
	private function __construct($currentPage, $totalResults, $perPageResults)
	{
		$this->setTotalResults($totalResults);  //总记录数
		$this->setPerPageResults($perPageResults);  //每页显示6条记录
		$this->setPerPagePages(4);  //如果一页显示完所有的页码，则此参数 = 0，如果对页码进行分页，参数 = 4 为最佳

		$this->setCurrentPage($currentPage);  //当前的页数

		$this->calculate();
	}
	
	private function __clone()
	{
	}
	
	/**
	 * @param int $currentPage 当前的页
	 * @param int $totalResults 总的记录条数
	 * @param int $perPageResults 每页显示的记录数
	 */
	public static function getInstance($currentPage = 1, $totalResults = 0, $perPageResults = 6)
	{
		if (null === self::$_instance) 
			self::$_instance = new self($currentPage, $totalResults, $perPageResults);
		
		return self::$_instance;
	}
	
	/**
	 * 对分页参数进行计算
	 * 
	 * @return Object $this
	 */
	public function calculate()
	{
		if ($this->_canCalculate()) 
		{
			$this->_startResult = ($this->_currentPage - 1) * $this->_perPageResults;
			$this->_totalPages  = floor(($this->_totalResults + $this->_perPageResults - 1)/$this->_perPageResults);
			if ($this->_perPagePages > 0) 
			{
				$this->_P_totalPages   = floor(($this->_totalPages + $this->_perPagePages -1)/$this->_perPagePages);
				$this->_P_currentPage  = ceil($this->_currentPage/$this->_perPagePages);
				$this->_startPage      = ($this->_P_currentPage - 1) * $this->_perPagePages + 1;
				$this->_endPage        = $this->_startPage + $this->_perPagePages - 1;
				$this->_endPage        = $this->_endPage < $this->_totalPages ? $this->_endPage : $this->_totalPages;
				$this->_prePage        = $this->_startPage > 1 ? $this->_startPage - 1 : 1;
				$this->_nextPage       = $this->_endPage < $this->_totalPages ? $this->_endPage + 1 : $this->_totalPages;
			}
		}
		return $this;
	}
	/**
	 * 目前所有的参数是否足够供计算使用
	 * 
	 * @return boolean
	 */
	protected function _canCalculate()
	{
		return ($this->_currentPage > 0 && $this->_totalResults > 0 && $this->_perPageResults > 0);
	}
	/**
	 * 设置总的记录条数
	 * 
	 * @param int $totalResults
	 * @return Object $this
	 */
	public function setTotalResults($totalResults)
	{
		$this->_totalResults = (int) $totalResults;
		if ($this->_totalResults < 0)
			throw new Exception('TotalResults count not less than 0');
			
		return $this;
	}
	/**
	 * 重新设置每页显示的记录数
	 * 
	 * @param int $perPageResults
	 * @return Object $this
	 */
	public function setPerPageResults($perPageResults)
	{
		$this->_perPageResults = (int) $perPageResults;
		if ($this->_perPageResults === 0) 
			$this->_perPageResults = $this->_totalResults;
		
		if ($this->_perPageResults < 1)
			throw new Exception('PerPageResults count not less than 1');
			
		return $this;
	}
	/**
	 * 设置每页显示页码数
	 * 
	 * @param int $perPagePages
	 * @return Object $this
	 */
	public function setPerPagePages($perPagePages)
	{
		$this->_perPagePages = (int) $perPagePages;
		if ($this->_perPagePages < 1)
			throw new Exception('PerPagePages count not less than 1');
			
		return $this;
	}
	/**
	 * 设置当前的页
	 * 
	 * @param int $currentPage
	 * @return Object $this
	 */
	public function setCurrentPage($currentPage)
	{
		$this->_currentPage = (int) $currentPage;
		if ($this->_currentPage < 1)
			throw new Exception('CurrentPage count not less than 1');
			
		return $this;
	}
	
	/**
	 * 显示分页列表函数  A 标签显示链接
	 * 
	 * @param string $link 链接前缀，如index.php?pageno=
	 * @param string $type self::URL_JS self::URL_A
	 * @param string $style 为没有链接的页码的样式
	 * @return string 页码
	 */
	public function display($link = '', $type = self::URL_JS, $style = 'color:#ff0000;font-weight:bold;')
	{	
		if($this->_totalPages <= 1) 
			return ;
		
		$first = $pre = $front = $list = $back = $next = $last = $js_left = $js_right = '';
		if ($type === self::URL_JS) 
		{
			$js_left = 'javascript:pageJump(\'';
			$js_right = '\');';
		}
		if ($this->_perPagePages > 0) 
		{
			$front = $this->_startPage > 1 ? '&nbsp;...&nbsp;' : '';
			$back  = $this->_endPage < $this->_totalPages ? '&nbsp;...&nbsp;' : '';
			
			$perPagePages_AVG = $this->_perPagePages%2 === 0 ? 
				$this->_perPagePages/2 : ceil($this->_perPagePages/2) - 1;
				
			$startPage = $this->_currentPage - $perPagePages_AVG;
			$endPage   = $this->_currentPage + $perPagePages_AVG;
			if ($startPage <= 1) 
			{
				$startPage = 2;
				$endPage = $startPage + $this->_perPagePages;
			}
			if ($endPage >= $this->_totalPages) 
			{
				$endPage = $this->_totalPages - 1;
				$startPage = $endPage - $this->_perPagePages;
				$startPage = $startPage > 2 ? $startPage : 2;
			}
			for ($i=$startPage; $i<=$endPage; $i++) 
				$list .= $i != $this->_currentPage ? 
					"&nbsp;<a href=\"{$js_left}{$link}{$i}{$js_right}\">$i</a>&nbsp;" : "&nbsp;<a style=\"$style\">$i</a>&nbsp;";
			
			$first = 1 < $this->_currentPage ? 
				"&nbsp;<a href=\"{$js_left}{$link}1{$js_right}\">1</a>&nbsp;" : "&nbsp;<a style=\"$style\">1</a>&nbsp;";
			
			$last  = $this->_currentPage < $this->_totalPages ? 
				"&nbsp;<a href=\"{$js_left}{$link}{$this->_totalPages}{$js_right}\">{$this->_totalPages}</a>&nbsp;" : 
				"&nbsp;<a style=\"$style\">{$this->_totalPages}</a>&nbsp;";
		}
		$pre = 1 < $this->_currentPage ? 
			"&nbsp;<a href=\"{$js_left}{$link}" . ($this->_currentPage-1) . "$js_right\">上一页</a>&nbsp;" : '';
		
		$next = $this->_currentPage < $this->_totalPages ? 
			"&nbsp;<a href=\"{$js_left}{$link}" . ($this->_currentPage+1) . "$js_right\">下一页</a>&nbsp;" : '';
		
		return $pre . $first . $front . $list . $back . $last . $next;
	}
	
	public function __get($name)
	{
		return $this->$name;
	}
}
